import numpy as np
import pandas as pd
import scipy.stats as st
import empyrical as ep
from dateutil.parser import parse


'''标准化函数'''
def standardize(s, ty=2):
    '''
    s为Series数据
    ty为标准化类型:1 MinMax,2 Standard,3 maxabs
    '''
    data = s.dropna().copy()
    if int(ty) == 1:
        re = (data - data.min()) / (data.max() - data.min())
    elif ty == 2:
        re = (data - data.mean()) / data.std()
    elif ty == 3:
        re = data / 10 ** np.ceil(np.log10(data.abs().max()))
    return re


'''过滤ST股票'''
#     sec_info_df = get_extras('is_st', securities, end_date=watch_date, df=True, count=1).iloc[0]
def del_st_stock(sec_info_df: pd.DataFrame, watch_date: str) -> list:
    return sec_info_df[sec_info_df == False].dropna().index.tolist()


'''计算ic'''
def src_ic(df: pd.DataFrame) -> pd.DataFrame:
    f = [col for col in df.columns if col != 'next_ret']
    _ic = df[f].apply(lambda x: st.spearmanr(x, df['next_ret'])[0])
    return _ic


'''获取分组'''
def add_group(ser: pd.Series, N: int = 5) -> pd.Series:
    name = ['G%s' % x for x in range(1, N+1)]
    return pd.qcut(ser, N, labels=name,duplicates='drop')


'''获取分组收益率'''
def get_algorithm_ret(factor_df: pd.DataFrame, col: str) -> pd.DataFrame:
    grp_n = 5
    group_ser = factor_df.groupby(level='date')[col].apply(add_group, N= grp_n)
    group_df = pd.concat((factor_df['next_ret'], group_ser), axis=1)

    group_ret = pd.pivot_table(group_df.reset_index(
    ), index='date', columns=col, values='next_ret')
    group_ret.columns = list(map(str, group_ret.columns))
    group_ret['excess_ret'] = group_ret['G1'] - group_ret['G5']

    return group_ret


'''获取多空收益'''
def get_excess_ret(factor_df: pd.DataFrame, col: list) -> pd.DataFrame:
    if isinstance(col, (str, float, int)):
        col = [col]

    df = pd.concat((get_algorithm_ret(factor_df, x)[
                   'excess_ret'] for x in col), axis=1)
    df.columns = col
    return df


'''组合收益风险指标，返回的df包含年化收益率、年化波动率、最大回撤三行，列为不同的λ值'''
def risk_indicator_tear(returns: pd.DataFrame, period: str = 'monthly') -> pd.DataFrame:
    tear = pd.DataFrame()
    tear['annual_return'] = ep.annual_return(returns, period)
    tear['annual_volatility'] = returns.apply(lambda x: ep.annual_volatility(x, period))
    tear['max_drawdown'] = returns.apply(lambda x: ep.max_drawdown(x))

    return tear.T.style.format('{:.2%}') # 上述3个指标由列转行